package com.example.service;

import com.example.annotation.Refresh;
import com.example.dto.RefreshBean;
import com.example.dto.RefreshField;
import com.example.proxy.DefaultProxyBean;
import com.example.proxy.DefaultProxyBeanHelper;
import com.example.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class SysBeanServiceImpl implements SysBeanService, BeanPostProcessor, ApplicationContextAware {

    private static final Logger log = LoggerFactory.getLogger(SysBeanServiceImpl.class);

    //扫描出所有待刷新的bean
    private Map<String, RefreshBean> refreshBeanMap = new ConcurrentHashMap<>();

    //保存所有的代理对象
    private List<DefaultProxyBean> refreshProxyBeans = new Vector<>();

    //spring容器
    private ApplicationContext applicationContext;

    /***
     * 拿到spring容器
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /****
     * 查询出标记了需要刷新的字段信息
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().isAnnotationPresent(Refresh.class)) {
            try {
                RefreshBean refreshBean = scanRefreshBean(bean, beanName);
                this.refreshBeanMap.put(beanName, refreshBean);
                return DefaultProxyBeanHelper.createProxy(refreshBean, applicationContext);
            } catch (Exception e) {
                log.warn("获取待刷新bean信息失败: " + e.getMessage());
            }
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    /****
     * 扫描出来所有的需要刷新的bean内容
     * @param bean
     * @param beanName
     * @return
     * @throws Exception
     */
    @Override
    public RefreshBean scanRefreshBean(Object bean, String beanName) throws Exception {
        RefreshBean refreshBean = new RefreshBean(beanName, bean);
        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Value.class)) {
                RefreshField refreshField = scanRefreshField(bean, beanName, field);
                refreshBean.getFields().add(refreshField);
            }
        }
        return refreshBean;
    }

    /***
     * 把可能綁定屬性的字段遍曆出來
     * @param bean
     * @param beanName
     * @param field
     * @return
     * @throws Exception
     */
    @Override
    public RefreshField scanRefreshField(Object bean, String beanName, Field field) throws Exception {
        Value value = field.getAnnotation(Value.class);
        field.setAccessible(true);
        RefreshField refreshField = new RefreshField();
        refreshField.setField(field);
        refreshField.setFieldClass(field.getType());
        refreshField.setFieldName(field.getName());
        refreshField.setFieldValue(field.get(bean));
        refreshField.setFieldKey(StringUtils.getSpringValue(value.value()));
        return refreshField;
    }

    /****
     * 保存spring的所有代理對象
     * @return
     */
    @Override
    public List<DefaultProxyBean> getRefreshProxyBeans() {
        return refreshProxyBeans;
    }
}
